﻿using System;
using UnityEditor;
using UnityEngine;
using System.Reflection;

namespace HKTools
{
    [CustomPropertyDrawer(typeof(BaseHKEnum), true)]
    public class HKEnumDrawer : PropertyDrawer
    {
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            var proxyProp = property.FindPropertyRelative(BaseHKEnum.kProxyPropName);
            var indexProp = property.FindPropertyRelative(BaseHKEnum.kIndexPropName);
            var valueProp = property.FindPropertyRelative(BaseHKEnum.kValuePropName);
            var propObject = GetTargetObjectOfProperty(property);

            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = property.hasMultipleDifferentValues;

            var enumValue = (Enum)((BaseHKEnum)propObject).valueObject;
            enumValue = EditorGUI.EnumPopup(position, label, enumValue);

            EditorGUI.showMixedValue = false;
            if (EditorGUI.EndChangeCheck())
            {
                int intValue = (int)Convert.ChangeType(enumValue, enumValue.GetType());
                valueProp.intValue = intValue;
                indexProp.intValue = intValue;
                proxyProp.stringValue = enumValue.ToString();
            }
        }

        private object GetTargetObjectOfProperty(SerializedProperty prop)
        {
            var path = prop.propertyPath.Replace(".Array.data[", "[");
            object obj = prop.serializedObject.targetObject;
            var elements = path.Split('.');
            foreach (var element in elements)
            {
                int leftBracketIndex = element.IndexOf("[");
                if (leftBracketIndex >= 0)
                {
                    int rightBracketIndex = element.IndexOf("]", leftBracketIndex);
                    var elementName = element.Substring(0, leftBracketIndex);
                    var index = System.Convert.ToInt32(element.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1));
                    obj = GetValue_Imp(obj, elementName, index);
                }
                else
                {
                    obj = GetValue_Imp(obj, element);
                }
            }
            return obj;
        }

        static object GetValue_Imp(object source, string name)
        {
            if (source == null)
                return null;
            var type = source.GetType();

            while (type != null)
            {
                var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                if (f != null)
                    return f.GetValue(source);

                var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                if (p != null)
                    return p.GetValue(source, null);

                type = type.BaseType;
            }
            return null;
        }

        static object GetValue_Imp(object source, string name, int index)
        {
            var enumerable = GetValue_Imp(source, name) as System.Collections.IEnumerable;
            if (enumerable == null) return null;
            var enm = enumerable.GetEnumerator();

            for (int i = 0; i <= index; i++)
            {
                if (!enm.MoveNext()) return null;
            }
            return enm.Current;
        }
    }
}